import Vue from 'vue';
import { Subject } from 'rxjs';
import AppSheetService from './app-sheet-service';
import { Component, Inject, Prop } from 'vue-property-decorator';
import { AppVisualCtrl } from './app-visual-ctrl/app-visual-ctrl';
import { AppVisualGrid } from './app-visual-grid/app-visual-grid';
import { AppVisualForm } from './app-visual-form/app-visual-form';
import { AppCtrlDesign } from './app-ctrl-design/app-ctrl-design';
import { CtrlEvent, CtrlType, ISheetCtrl, ISheetParam } from '../interface';
import './app-visual-sheet.less';
import { SheetUtil } from '../utils';

/**
 * sheet组件
 *
 * @export
 * @class AppVisualSheet
 * @extends {Vue}
 */
@Component({
    components: {
        AppVisualCtrl,
        AppVisualGrid,
        AppVisualForm,
        AppCtrlDesign
    }
})
export class AppVisualSheet extends Vue {

    /**
     * @description 视图实例
     * @type {*}
     * @memberof AppVisualSheet
     */
    @Prop() public viewInstance: any;

    /**
     * 是否可设计控件
     *
     * @type {*}
     * @memberof AppVisualSheet
     */
    @Prop({ default: true }) public enableDesgin?: boolean;

    /**
     * @description 传入自定义参数
     * @type {*}
     * @memberof AppVisualSheet
     */
    @Prop() public options: any;

    /**
     * @description store对象
     * @memberof AppVisualSheet
     */
    @Prop() public store: any;

    /**
     * @description i18n对象
     * @memberof AppVisualSheet
     */
    @Prop() public i18n: any;

    /**
     * @description router对象
     * @memberof AppVisualSheet
     */
    @Prop() public router: any;

    /**
     * 注入加载行为
     *
     * @memberof AppVisualSheet
     */
    @Inject("reload")
    reload!: any;

    /**
     * @description 控件ID
     * @memberof AppVisualSheet
     */
    public controlId: string | undefined = '';

    /**
     * @description  sheet状态对象
     * @type {Subject<ISheetParam>}
     * @memberof AppVisualSheet
     */
    public sheetState: Subject<ISheetParam> = new Subject();

    /**
     * @description 激活项控件
     * @memberof AppVisualSheet
     */
    public activeCtrlItem: any;

    /**
     * @description sheet服务
     * @type {(AppSheetService|null)}
     * @memberof AppVisualSheet
     */
    public sheetService: AppSheetService | null = null;

    /**
     * @description 初始完成
     * @memberof AppVisualSheet
     */
    public created() {
        this.sheetService = new AppSheetService({ key: this.viewInstance.codeName, userOptions: this.options, enableDesgin: this.enableDesgin });
    }

    /**
     * @description 挂载完成
     * @memberof AppVisualSheet
     */
    public mounted() {
        this.getSheetOpts().then((result: any) => {
            this.renderWorkBook(result, this.sheetService?.getSheetCtrlOpts());
        })
    }

    /**
     * @description 组件销毁
     * @memberof AppVisualSheet
     */
    public destory() {
        (window as any).$("#luckysheet-ctrl-showBoxs .ctrl-list").empty();
        SheetUtil.destroy();
    }

    /**
     * @description 获取sheet参数
     * @memberof AppVisualSheet
     */
    public async getSheetOpts(): Promise<any> {
        const result = await this.sheetService?.getSheetOpts();
        this.controlId = result?.container;
        return result;
    }

    /**
     * @description 控件初始化完成
     * @param {*} arg
     * @memberof AppVisualSheet
     */
    public onCtrlInitd(arg: any) {
        this.sheetService?.setSheetCtrlOpts(arg.id, arg);
    }

    /**
     * @description 设计态拖拽
     * @param {*} arg
     * @memberof AppVisualSheet
     */
    public onCtrlDrag(arg: any) {
        this.sheetService?.setSheetCtrlOpts(arg.id, arg);
        this.sheetState.next({ tag: 'design', action: 'REFRESH', data: arg });
    }

    /**
     * @description 设计态调整大小
     * @param {*} arg
     * @memberof AppVisualSheet
     */
    public onCtrlResize(arg: any) {
        this.sheetService?.setSheetCtrlOpts(arg.id, arg);
        this.sheetState.next({ tag: 'design', action: 'REFRESH', data: arg });
    }

    /**
     * @description 控件配置变化
     * @param {*} arg
     * @memberof AppVisualSheet
     */
    public onCtrlConfChange(arg: any) {
        this.sheetService?.setSheetCtrlOpts(arg.id, arg);
    }

    /**
     * @description 删除控件
     * @param {*} arg
     * @memberof AppVisualSheet
     */
    public onCtrlRemove(arg: any) {
        this.sheetService?.removeSheetCtrlOpt(arg.id);
        this.reload();
    }

    /**
     * @description 取消激活
     * @param {*} arg
     * @memberof AppVisualSheet
     */
    public onCtrlDeactivated(arg: any) {
        this.activeCtrlItem = null;
        if (arg) {
            this.sheetState.next({ tag: 'design', action: 'CLOSE', data: arg });
        }
    }

    /**
     * @description 激活
     * @param {*} arg
     * @memberof AppVisualSheet
     */
    public onCtrlActivated(arg: any) {
        this.activeCtrlItem = arg;
        if (arg) {
            this.sheetState.next({ tag: 'design', action: 'OPEN', data: arg });
        }
    }

    /**
     * @description 控件初始化参数变化
     * @param {*} options
     * @memberof AppVisualSheet
     */
    public onCtrlOptsChange(options: any) {
        this.sheetState.next({ tag: options.id, action: 'CLEAR', data: this.sheetService?.getSheetCtrlOptById(options.id) });
        this.sheetService?.setSheetCtrlOpts(options.id, options);
        (window as any).$("#luckysheet-ctrl-showBoxs .ctrl-list").empty();
        this.reload();
    }

    /**
     * @description 处理鼠标点击事件
     * @memberof AppVisualSheet
     */
    public handleCellMousedown(cell: any, position: any, sheetFile: any, ctx: any) {
        const ctrlArray = this.sheetService?.getSheetCtrlOpts();
        if (ctrlArray && ctrlArray.length > 0) {
            ctrlArray.forEach((ctrl: ISheetCtrl) => {
                this.sheetState.next({ tag: ctrl.id, action: 'CELLMOUSEDOWN', data: { cell, position, sheetFile } });
            })
        }
        return false;
    }

    /**
     * @description 处理sheet操作
     * @param {*} data
     * @memberof AppVisualSheet
     */
    public handleSheetUpdate(data: any) {
        const ctrlArray = this.sheetService?.getSheetCtrlOpts();
        if (ctrlArray && ctrlArray.length > 0) {
            ctrlArray.forEach((ctrl: ISheetCtrl) => {
                this.sheetState.next({ tag: ctrl.id, action: 'UPDATE', data: data });
            })
        }
    }

    /**
     * @description 处理渲染上下文菜单
     * @param {*} cell
     * @param {*} position
     * @param {*} sheetFile
     * @param {*} event
     * @memberof AppVisualSheet
     */
    public handleRenderContextMenu(cell: any, position: any, sheetFile: any, event: any) {
        const ctrlArray = this.sheetService?.getSheetCtrlOpts() || [];
        const formCtrls = ctrlArray.filter((ctrl: ISheetCtrl) => { return ctrl.type == CtrlType.VISUAL_FORM });
        if (formCtrls && formCtrls.length > 0) {
            formCtrls.forEach((form: ISheetCtrl) => {
                this.sheetState.next({
                    tag: form.id, action: 'RENDERCONTEXTMENU', data: {
                        cell: cell,
                        position: position,
                        sheetFile: sheetFile,
                        event: event
                    }
                })
            })
        }
    }

    /**
     * @description 绘制工作簿
     * @memberof AppVisualSheet
     */
    public renderWorkBook(sheetSettingOpts: any, sheetCtrlOpts: any) {
        const _this = this;
        SheetUtil.create({
            ...sheetSettingOpts,
            hook: {
                workbookCreateAfter: (json: any) => {
                    _this.renderCtrlItem(sheetCtrlOpts);
                },
                cellMousedownBefore: (cell: any, position: any, sheetFile: any, ctx: any) => {
                    return _this.handleCellMousedown(cell, position, sheetFile, ctx);
                },
                updated: (operate: any) => {
                    _this.handleSheetUpdate(operate);
                },
                onRenderContextMenu: (cell: any, position: any, sheetFile: any, event: any) => {
                    this.handleRenderContextMenu(cell, position, sheetFile, event);
                }
            }
        });
    }

    /**
     * @description 绘制控件项
     * @param {*} items
     * @memberof AppVisualSheet
     */
    public renderCtrlItem(items: any) {
        if (items && items.length > 0) {
            const _this = this;
            items.forEach((item: any) => {
                const props = { id: item.id, sheetState: this.sheetState, enableDesgin: this.enableDesgin };
                const options = {
                    store: this.store,
                    router: this.router,
                    i18n: this.i18n
                }
                let activatedItem: any;
                let activatedEvent: any = {
                    [CtrlEvent.INITD]: (arg: any) => { _this.onCtrlInitd(arg) },
                    [CtrlEvent.ACTIVATED]: (arg: any) => { _this.onCtrlActivated(arg) },
                    [CtrlEvent.DEACTIVATED]: (arg: any) => { _this.onCtrlDeactivated(arg) },
                    [CtrlEvent.DRAG]: (arg: any) => { _this.onCtrlDrag(arg) },
                    [CtrlEvent.RESIZE]: (arg: any) => { _this.onCtrlResize(arg) },
                    [CtrlEvent.CONFCHANGE]: (arg: any) => { _this.onCtrlConfChange(arg) },
                    [CtrlEvent.REMOVE]: (arg: any) => { _this.onCtrlRemove(arg) }
                }
                // 虚拟表格
                if (Object.is(item.type, 'GRID')) {
                    const { position, columns } = item;
                    Object.assign(props, { position: position, columnArray: columns });
                    activatedItem = AppVisualGrid;
                } else if (Object.is(item.type, 'FORM')) {
                    Object.assign(props, { position: item.position, sheetConfig: item.sheetConfig, items: item.items });
                    activatedItem = AppVisualForm;
                } else {
                    // 控件
                    Object.assign(props, { position: item.position });
                    activatedItem = AppVisualCtrl;
                }
                Vue.prototype.$i18n = this.i18n;
                Vue.prototype.$store = this.store;
                const vm = new Vue({
                    ...options,
                    render(h) {
                        return h(activatedItem,
                            {
                                props,
                                on: activatedEvent
                            }, [_this.$slots.default]);
                    }
                }).$mount();
                (window as any).$("#luckysheet-ctrl-showBoxs .ctrl-list").append(vm.$el);
            });
        }
    }

    /**
     * @description 绘制
     * @return {*} 
     * @memberof AppVisualSheet
     */
    public render(h: any) {
        return (
            <div class="app-visual-sheet">
                <div
                    id={this.controlId}
                    style="margin:0px;padding:0px;position:absolute;width:100%;height:100%;left: 0px;top: 0px;"
                ></div>
                {this.enableDesgin ? <app-ctrl-design viewInstance={this.viewInstance} sheetState={this.sheetState} onChange={(options: any) => { this.onCtrlOptsChange(options) }} /> : null}
            </div>

        )
    }
}